<?php
require __DIR__.'/class/cache.interface.php';
require __DIR__.'/class/cache.redis.php';
require __DIR__.'/class/cache.memcache.php';
require __DIR__.'/class/cache.file.php';
require __DIR__.'/common/function.php';

/**
 * 语言调用类
 * 说明：实现语言文件惰性加载，只有在缓存得不到数据的情况下，系统才会载入语言
 *
 * 使用方法：
 * Language:get('hello'); //根据key得到语言
 * Language:set('goodbye','再见'); //设置和修改语言
 * Language:remove('goodbye'); //动态删除语言(只对当前访问有效)
 * Language:set_media($save_media); 设置缓存介质
 * Language:set_lang($lang); 设置语言，对应data/$lang 目录
 * Language:set_clear(); //设置调试模式，开发使用
 *
 * 示例(调试)：
 * Language:set_clear();
 * Language:get('hello');
 *
 * 正式：
 * Language:get('hello');
 */
final class Language{
    private static $_mediaObject;
    private static $save_media; // file,redis,memcache 缓存类取名按 CacheRedis 格式
    private static $lang ; //语言
    private static $default_cache = 'file'; //当启用失败时默认启用file缓存
    private static $is_cache = 0; // 调试模式, 1表示不开启惰性缓存，每次都会载入文件。或者直接调用Language:set_clear();即可
    //让程序初始化的时候new一次自己，让程序结束的时候自动调用__destruct方法
    private static $lock = null;
    private static $check_key = 0; // 解决重复的问题
    private static $issue_key = ''; // 可能会出问题的key

    /**
     * 加载语言
     * $examine_key 是否检查key ,默认为检查
     */
    private static function load($examine_key = true){
        if (self::$check_key) return;
        self::$lock = new self;
        $lang_dir = __DIR__.'/data/'.self::$lang;
        $dir_list = dir_list($lang_dir);
        self::load_class();//自动加载类
        switch (self::$save_media){
            case 'redis':
            case 'memcache':
                //将所有语言文件加载到redis
                foreach ($dir_list as $file){
                    if(pathinfo($file,PATHINFO_EXTENSION) == 'ini'){
                        $lang_word = parse_ini_file($lang_dir.'/'.$file);
                        foreach ($lang_word as $key_word=>$word){
                            self::$_mediaObject->set($key_word,$word);
                        }
                    }
                }
                break;
            case 'file':
                $a = parse_ini_file(__DIR__.'/data/vi_VN/language_admin.ini');
                //将所有语言文件加载到文件
                $lang_word_array = array();
                foreach ($dir_list as $file){
                    if(pathinfo($file,PATHINFO_EXTENSION) == 'ini'){
                        $lang_word = parse_ini_file($lang_dir.'/'.$file);

                        $lang_word_array = array_merge($lang_word_array,$lang_word);
                    }
                }
                self::$_mediaObject->set_all($lang_word_array);
                break;
            default:
                throws_Exception('language system error');
        }
        if($examine_key){
            self::$check_key = 1;
            if(empty(self::get(self::$issue_key))){
                throws_Exception('key inexistence'); //当前key不存在
            }
        }
    }

    /**
     * 获取缓存类对象
     */
    private static function load_class(){
        if(empty(self::$_mediaObject)){
            //读取配置文件
            $self_config = parse_ini_file(__DIR__.'/config/config.ini');

            self::$save_media = $self_config['save_media'];
            if(empty(self::$lang)){
                self::$lang = $self_config['lang'];
            }
            $redis_ini = parse_ini_file(__DIR__.'/config/'.self::$save_media.'.ini');

            try{
                $reflect = new ReflectionClass('Cache'.ucfirst(self::$save_media));
                self::$_mediaObject = $reflect->newInstance();
                $connect_result = self::$_mediaObject->connect($redis_ini,self::$lang);
            }catch (Exception $e){
                $connect_result = false;
            }
            if(empty($connect_result)){
                //启动失败,启用默认缓存
                if(self::$default_cache != self::$save_media){
                    $write_ini = array(
                        'save_media'=>self::$default_cache,
                        'lang'=>self::$lang,
                    );
                    //将配置文件修改为默认缓存
                    $white_result =  write_config_ini_file(__DIR__.'/config/config.ini',$write_ini);
                    if($white_result){
                        //设置时间地区
                        date_default_timezone_set("PRC");
                        //写log
                        file_put_contents(__DIR__.'/error.log', '---------------缓存组件：'.self::$save_media.' 连接失败,现在已载入默认缓存：'.self::$default_cache.'---------------时间'.date('Y-m-d H:i:s')."\r\n", FILE_APPEND | LOCK_EX);
                        //设置file缓存
                        self::$save_media = self::$default_cache;
                        self::$_mediaObject = null;
                        self::load_class();
                    }else{
                        throws_Exception('language config write error');
                    }
                }else{
                    throws_Exception('language default Cache boot failure');
                }
            }
        }
        return self::$_mediaObject;
    }

    /**
     * 返回缓存类
     * @param $key 
     */
    private static function load_cache($key = ''){
        $cache_class = self::load_class();
        if(empty($cache_class->get($key)) || self::$is_cache){
            self::$issue_key = $key;
            //初始化该类
            self::load();
        }
    }

    /**
     * 根据key获取该语言
     * @param $key
     * @return mixed
     * @throws Exception
     */
    public static function get($key){
        self::load_cache($key);
        return self::$_mediaObject->get($key);
    }

    /**
     * 动态修改语言缓存
     * @param $key
     * @param $val
     * @throws Exception
     */
    public static function set($key,$val){
        self::load_cache();
        return self::$_mediaObject->set($key,$val);
    }

    /**
     * 设置缓存介质
     * @param $save_media
     */
    public static function set_media($save_media){
        self::$save_media = $save_media;
    }

    /**
     * 设置语言
     * @param $lang
     */
    public static function set_lang($lang){
        self::$lang = $lang;
        //设置语言后，重新加载缓存
        self::load(false);
    }

    /**
     * 设置惰性缓存
     */
    public static function set_clear(){
        self::$is_cache = 1;
    }

    /**
     * 将$_mediaObject 设置为空，可以让程序重新载入语言对象
     */
    public static function set_obj_null(){
        self::$_mediaObject = null;
    }

    /**
     * 动态删除语言缓存
     * @param $key
     * @throws Exception
     */
    public static function remove($key){
        self::load_cache();
        return self::$_mediaObject->remove($key);
    }

    public function __destruct(){
        if(self::$_mediaObject != null){
            self::$_mediaObject->close();
        }
    }

    public function get_lang(){
        return self::$lang;
    }

}
//Language::set_clear();